package com.platform.schedule.dynamic.builder;

import com.platform.schedule.dynamic.annotation.DynamicSchedule;
import com.platform.schedule.dynamic.annotation.DynamicScheduleMethod;
import com.platform.schedule.dynamic.annotation.DynamicScheduleSet;
import com.platform.schedule.dynamic.service.impl.DynamicScheduleTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.Arrays;
import java.util.Map;

/**
 * 动态定时任务Bean构建器
 * <p>
 *
 * @author: WangYang
 * @date: 2018-01-04 11:18
 * @version: 1.0
 * @since 1.8
 */
@Slf4j
public class DynamicScheduleContextBeanBuilder implements ApplicationContextAware,
        BeanDefinitionRegistryPostProcessor {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // 构建任务处理器
        Map<String, Object> taskMap = applicationContext.getBeansWithAnnotation(DynamicSchedule.class);
        taskMap.values().stream().forEach(item -> {
            DynamicSchedule annotation = item.getClass().getAnnotation(DynamicSchedule.class);
            //创建bean信息.
            BeanDefinitionBuilder beanDefinitionBuilder =
                    BeanDefinitionBuilder.genericBeanDefinition(DynamicScheduleTemplate.class);
            beanDefinitionBuilder.addPropertyValue("bean", item);
            beanDefinitionBuilder.addPropertyValue("methodName", annotation.method());
            beanDefinitionBuilder.addPropertyValue("name", annotation.name());
            beanDefinitionBuilder.addPropertyValue("cron", annotation.cron());
            // 动态注册bean.
            registry.registerBeanDefinition(annotation.name(),
                    beanDefinitionBuilder.getBeanDefinition());
        });

        Map<String, Object> scheduleSetMap = applicationContext.getBeansWithAnnotation(DynamicScheduleSet.class);
        scheduleSetMap.values().stream().forEach(bean -> {
            Class cls = bean.getClass();
            Arrays.stream(cls.getMethods()).forEach(method -> {
                DynamicScheduleMethod annotation = method.getAnnotation(DynamicScheduleMethod.class);
                if (annotation != null) {
                    //创建bean信息.
                    BeanDefinitionBuilder beanDefinitionBuilder =
                            BeanDefinitionBuilder.genericBeanDefinition(DynamicScheduleTemplate.class);
                    beanDefinitionBuilder.addPropertyValue("bean", bean);
                    beanDefinitionBuilder.addPropertyValue("methodName", method.getName());
                    beanDefinitionBuilder.addPropertyValue("name", annotation.name());
                    beanDefinitionBuilder.addPropertyValue("cron", annotation.cron());
                    // 动态注册bean.
                    registry.registerBeanDefinition(annotation.name(),
                            beanDefinitionBuilder.getBeanDefinition());
                }
            });
        });
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}
